package com.hl.card.pay.controller;
import com.alibaba.fastjson.JSONObject;
import com.hl.card.common.util.CurrencyUtil;
import com.hl.card.common.util.HttpUtils;
import com.hl.card.common.util.ResponseModel;
import com.hl.card.common.util.ResponseObject;
import com.hl.card.pay.config.Constant;
import com.hl.card.pay.dto.MerchantDto;
import com.hl.card.pay.dto.PayDto;
import com.hl.card.pay.service.CommonService;
import com.hl.card.pay.service.PayService;
import com.hl.card.pay.util.Base64Tool;
import com.hl.card.pay.util.PayDigestUtil;
import com.hl.card.pay.util.PayTool;
import com.hl.card.pay.vo.Coin;
import com.hl.card.pay.vo.PayVo;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Controller
public class PayController {

    private Logger logger= LoggerFactory.getLogger(this.getClass());
    @Autowired
    private PayService payService;
    @Autowired
    private CommonService commonService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @RequestMapping("payTest")
    public String patTest(){
        return "/pay/payTest.html";
    }
    @Value("${pay.config.staticUrl}")
    private  String  staticUrl;
    @Value("${pay.config.apiUri}")
    private String apiUri;
    @Value("${pay.config.bibiUriPrefix}")
    private String bibiUriPrefix;
    /**
     * 提交订单信息
     * @param payVo
     * @return
     */
    @RequestMapping("requestPay")
    @ResponseBody
    public ResponseModel requestPay(@RequestBody PayVo payVo){
        logger.info("第一个进来的字符串："+JSONObject.toJSONString(payVo));
        ResponseModel responseModel=new ResponseModel();
        String s = Base64Tool.encode(payVo);
        responseModel.setData(staticUrl+"/payInfo?params="+s);
        responseModel.setStatus("0000");
        return responseModel;
    }
    @RequestMapping("payInfo")
    public String payInfo(String params,Model model,HttpSession session){
        session.setAttribute("payVo",null);
        String repParam=  params.replaceAll(" ","+");
        PayVo payVo= Base64Tool.decode(repParam);
        payVo=payService.wrapPayVo(payVo);
        MerchantDto merchant= payService.getMerchantById(payVo.getMchId());
        payVo.setHtlAmount(payVo.getAmount());
        Map mapETH=payService.getEthAmount(payVo.getCnyAmount());
        String ethAmount=mapETH.get("echo").toString();
        List<Map> payChanelList=payService.getPayChanelSimple(payVo.getAsyn(),payVo.getUserId(),payVo.getAmount(),ethAmount);
        model.addAttribute("merchant",merchant);
        model.addAttribute("payChanelList",payChanelList);
        model.addAttribute("payVo",payVo);
        model.addAttribute("userId",payVo.getUserId());
        model.addAttribute("apiUri",apiUri);
        model.addAttribute("backUrl",payVo.getBackUrl());
        model.addAttribute("bibiUriPrefix",bibiUriPrefix);
        session.setAttribute("merchant",merchant);
        session.setAttribute("payChanelList",payChanelList);
        session.setAttribute("payVo",payVo);
        session.setAttribute("userId",payVo.getUserId());
        return "/pay/confirmPayment.html";
    }
    @RequestMapping("payconfirm")
    public String payconfirm(@RequestParam("channel") String channel,Model model,HttpSession session){
        PayVo payVo= (PayVo) session.getAttribute("payVo");
        session.setAttribute("oldVo",JSONObject.toJSON(payVo));
        logger.info("payVo.getAsyn():"+payVo.getAsyn()+"channel:"+channel);
        String channelId=payService.findChannelId(payVo.getAsyn(),channel);
        payVo.setChannel(channel);
        payVo.setCurrency(channel);
        payVo.setChannelId(channelId);
        if(channel.equals("htl")){
            payVo.setAmount(payVo.getHtlAmount());
            payVo.setEchoAmount(payVo.getHtlAmount());
        }
        List<Coin> coins= payVo.getCoins().stream().filter(coin ->coin.getCurrency().equals(channel)).collect(Collectors.toList());
        payVo.setCoins(coins);
        payVo.setAmount(coins.get(0).getAmount());
        payVo.setCurrency(coins.get(0).getCurrency());
        session.setAttribute("payVo",payVo);
        model.addAttribute("payVo",payVo);
        model.addAttribute("bibiUriPrefix",bibiUriPrefix);
        return "/pay/payconfirm.html";
    }
    /**
     * ajax pay
     * @param payPassword
     * @return
     */
    @PostMapping("doPay")
    @ResponseBody
    public ResponseModel doPay(@RequestParam("payPassword")String payPassword,HttpSession session){
        String userId= (String) session.getAttribute("userId");
        PayVo payVo= (PayVo) session.getAttribute("payVo");
        ResponseModel responseModel = new ResponseModel();
        int times = commonService.findPayError(userId);//支付密码错误次数
        boolean b = commonService.checkPayPassWord(userId,payPassword);//验证支付密码
        if (times > 4) {
            responseModel.setStatus("0001");
            responseModel.setData("密码输错次数超过上限！明天再试");
            return responseModel;
        }
        if (!b) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("msg", "交易密码错误");
            jsonObject.put("errorTimes", times + 1);
            responseModel.setStatus("0002");
            responseModel.setData(jsonObject);
        } else {
            Coin coin=payVo.getCoins().get(0);
            payVo.setChannel(coin.getCurrency());
            payVo.setCurrency(coin.getCurrency());
            payVo.setAmount(coin.getAmount());
            payVo.setChannelId(coin.getChannelId());
            ResponseModel re = payService.creteOrder(payVo);
            if(re.getStatus().equals("0000")){
                //使用两次支付
//                PayDto newPay= new PayDto();
//                BeanUtils.copyProperties(payVo,newPay);
//                String  s= (String) payService.pay(newPay);
//                JSONObject jsonObject=JSONObject.parseObject(s);
                //一次支付
                JSONObject jsonObject=JSONObject.parseObject(re.getData().toString());
                if(jsonObject.get("resCode")!=null&&jsonObject.get("resCode").equals("FAIL")){
                    responseModel.setStatus("0004");
                    responseModel.setData(jsonObject.get("errCodeDes"));
                    return responseModel;
                }
                if(jsonObject.get("isSuccess").equals(true)){
                    responseModel.setStatus("0000");
                    responseModel.setData("支付成功");
                }else{
                    responseModel.setStatus("0003");
                    responseModel.setData("支付系统错误");
                }
                // TODO 余额判断
        }else{
                responseModel.setStatus("0004");
                responseModel.setData("创建订单失败");
        }
        }
        return responseModel;
    }
    @RequestMapping("queryPayOrder")
    @ResponseBody
    public ResponseObject queryPayOrder(String mchId, String mchOrderNo){
        ResponseObject responseObject = new ResponseObject();
        responseObject.setErroCode(1);
        PayDto newPay= new PayDto();
        JSONObject result;
        newPay.setMchOrderNo(mchOrderNo);
        newPay.setMchId(mchId);
        String  res = (String) payService.quryPayOrder(newPay);
        if(StringUtils.isBlank(res)) {
            result = new JSONObject();
            result.put("msg", "网络错误");
            return responseObject;
        }
        JSONObject resObj = JSONObject.parseObject(res);
        if("SUCCESS".equals(resObj.getString("retCode")) && "SUCCESS".equalsIgnoreCase(resObj.getString("resCode").toString())) {
            result = resObj.getJSONObject("result");
            result.remove("extra");
            result.remove("payOrderId");
            result.remove("notifyCount");
            result.remove("updateTime");
            result.remove("channelAccount");
            result.remove("channelMchId");
            result.remove("param1");
            result.remove("param2");
            result.remove("notifyUrl");
            String currency = result.getString("currency");
            switch (currency) {
                case "cny":
                    result.put("amount", CurrencyUtil.converDisString(Long.parseLong(result.getString("amount")), currency));
                    result.put("currency", "元");
                    break;
                case "eth":
                    result.put("amount", CurrencyUtil.converGWEIToETHToStr(Double.parseDouble(result.getString("amount")), 2));
                    break;
                default:
                    break;
            }
            int status = result.getIntValue("status");
            if(status >= 2) {
                result.put("msg", "订单支付成功");
            }else if(status >= 0 && status <= 1){
                result.put("msg", "订单未支付");
            }else {
                result.put("msg", "订单错误");
            }
            responseObject.setErroCode(0);
            responseObject.setData(result);
        }else {
            result = new JSONObject();
            result.put("msg", resObj.getString("errCodeDes"));
            responseObject.setData(result);
            responseObject.setErroCode(1);
        }
        return responseObject;
    }
    @RequestMapping("payDetail")
    public String payDetail(Model model,HttpSession session){
        PayVo payVo= (PayVo) session.getAttribute("payVo");
        logger.info("payVo："+payVo);
        PayDto payDto=new PayDto();
        BeanUtils.copyProperties(payVo,payDto);
        String  res = (String) payService.quryPayOrder(payDto);
        if(StringUtils.isBlank(res)) {
            model.addAttribute("payResult","网络错误");
        }else {
            JSONObject resObj = JSONObject.parseObject(res);
            JSONObject result;
            if ("SUCCESS".equals(resObj.getString("retCode")) && "SUCCESS".equalsIgnoreCase(resObj.getString("resCode").toString())) {
                result = resObj.getJSONObject("result");
                int status = result.getIntValue("status");
                if (status >= 2) {
                    model.addAttribute("payResult", "订单支付成功");
                } else if (status >= 0 && status <= 1) {
                    model.addAttribute("payResult", "订单未支付");
                } else {
                    model.addAttribute("payResult", "订单错误");
                }
            } else {
                model.addAttribute("payResult", resObj.getString("errCodeDes"));
            }
        }
        logger.info("返回商城地址："+payVo.getReturnUrl());
        logger.info("返回商城地址："+payVo.getRedirectUrl());
        if(payVo.getReturnUrl()==null){
            payVo.setRedirectUrl(payVo.getRedirectUrl());
        }
        model.addAttribute("payVo",session.getAttribute("payVo"));
        session.setAttribute("oldVo",null);
        session.setAttribute("oldVo",null);
        session.removeAttribute("payVo");
        return "/pay/payDetail.html";
    }
    /**
     * 提交订单信息，返回支付选择页,用户选择了支付渠道后，在进行实际下单支付
     * @param params
     * @return
     */
    @RequestMapping("requestSelectPay")
    @ResponseBody
    public ResponseModel requestSelectPay(@RequestParam String params, Model model, HttpServletRequest request, HttpSession session){
        session.setAttribute("payVo",null);
        session.setAttribute("oldVo",null);
        session.setAttribute("version",(1+Math.random()*10));
        model.addAttribute("version",(1+Math.random()*10));
        PayVo payVo = JSONObject.parseObject(params, PayVo.class);
        logger.info("商城购买原始字符串"+JSONObject.toJSONString(payVo));
        MerchantDto merchant= payService.getMerchantById(payVo.getMchId());
        List<Map> payChanelList=payService.getPayChanelByMchId(payVo.getMchId());
        if(StringUtils.isEmpty(payVo.getCurrency())){
            payVo.setCurrency("cny");
        }
        if(payVo.getCoins()==null){
            payVo.setCoins(new ArrayList<>());
        }
        String payJson = JSONObject.toJSONString(payVo);
        logger.info("请求字符串");
        logger.info(payJson);
        String payKey = PayDigestUtil.md5(payJson, "UTF-8");
        stringRedisTemplate.opsForValue().set(payKey, payJson, 30, TimeUnit.MINUTES);//30分钟内不支付，就过期
        model.addAttribute("merchant",merchant);
        model.addAttribute("payChanelList",payChanelList);
        model.addAttribute("payVo",payVo);
        model.addAttribute("backUrl",payVo.getBackUrl());
        session.setAttribute("merchant",merchant);
        session.setAttribute("payChanelList",payChanelList);
        session.setAttribute("payVo",payVo);
        session.setAttribute("userId",payVo.getUserId());
        ResponseModel responseModel=new ResponseModel();
        responseModel.setData(staticUrl+"/selectPayment?params="+payKey);
        responseModel.setStatus("0001");
        return responseModel;
    }
    //用户选择支付渠道页面
    @RequestMapping("selectPayment")
    public String selectPayment(String params , ModelMap model, HttpServletRequest request, HttpServletResponse response, HttpSession session) throws IOException {
        System.out.println("进来的字符串"+params);
        String clientIp = HttpUtils.getIpAddr(request);
        //获取支付信息
        String payJson = stringRedisTemplate.opsForValue().get(params);
        PayVo payVo= JSONObject.parseObject(payJson, PayVo.class);
        payVo.setCurrency("cny");
        payVo.setClientIp(clientIp);
        MerchantDto merchant= payService.getMerchantById(payVo.getMchId());
        List<Map> payChanelList=payService.getPayChanelByMchId(payVo.getMchId());
        List<Map> payList=payService.getPayList();
        logger.info("currency"+payVo.getCurrency());
        payVo=payService.wrapPayVo(payVo);
        model.addAttribute("baseUrl",staticUrl);
        model.addAttribute("payKey",params);
        model.addAttribute("merchant",merchant);
        model.addAttribute("payChanelList",payChanelList);
        model.addAttribute("payVo",payVo);
        model.addAttribute("payList",payList);
        model.addAttribute("backUrl",payVo.getBackUrl());
        model.addAttribute("version",(1+Math.random()*(10-1+1)));
        session.setAttribute("payKey",params);
        session.setAttribute("merchant",merchant);
        session.setAttribute("payChanelList",payChanelList);
        session.setAttribute("payVo",payVo);
        session.setAttribute("userId",payVo.getUserId());
        session.setAttribute("payList",payList);
        //判断是否在微信内，如果在微信内,只能使用微信公总号支付
        String ua = request.getHeader("User-Agent");
        String client = "h5";
        if(org.apache.commons.lang3.StringUtils.isBlank(ua)) {
            String errorMessage = "User-Agent为空！";
        }else {
            //微信公众号内直接下单
            if(ua.contains("MicroMessenger")) {
                client = "wx";
                payVo.setChannelId("WX_JSAPI");
                ResponseModel re = payService.creteOrder(payVo);
                model.put("orderMap", re.getData());
                return "/pay/wxPayment.html";
            }
        }
        return "/pay/selectPayment_bak.html";
    }
    //根据用户选择的支付渠道进行支付下单
    @RequestMapping("createPayInfo")
    public String createPayInfo(@RequestParam String channelId, Model model,HttpServletResponse response, HttpSession session) throws IOException {
        if(channelId==null){
            return "/pay/payError.html";
        }
        String currency=payService.findCurrencyByChannelId(channelId);
        PayVo payVo= (PayVo) session.getAttribute("payVo");
        System.out.println("选择的支付渠道："+channelId);
        payVo.setChannelId(channelId);
        payVo.setCurrency(currency);
        payVo.setChannel(currency);
        MerchantDto merchant= payService.getMerchantById(payVo.getMchId());
        List<Map> payChanelList=payService.getPayChanelByMchId(payVo.getMchId());
        String remainPart=payService.getBlance(payVo);
        model.addAttribute("merchant",merchant);
        model.addAttribute("payChanelList",payChanelList);
        model.addAttribute("payVo",payVo);
        model.addAttribute("remainPart",remainPart);
        model.addAttribute("bibiUriPrefix",bibiUriPrefix);
        session.setAttribute("merchant",merchant);
        session.setAttribute("payChanelList",payChanelList);
        session.setAttribute("payVo",payVo);
        session.setAttribute("userId",payVo.getUserId());
        session.setAttribute("remainPart",remainPart);
        session.setAttribute("bibiUriPrefix",bibiUriPrefix);
        if(!currency.equals("cny")){
            return "forward:/payconfirm?channel="+currency;
        }
        ResponseModel re = payService.creteOrder(payVo);
        if(re.getStatus().equals("0000")){
            JSONObject payResult = (JSONObject) re.getData();
            if(StringUtils.isNotBlank(payResult.getString("payUrl"))) {//外部支付直接跳转支付地址：支付宝PC支付和H5直接跳转，微信H5直接跳转
                String payUrl = payResult.getString("payUrl");
                model.addAttribute("form",payUrl);
                if(payUrl.indexOf("http") == 0) {
                    response.sendRedirect(payUrl);
                }
                if("WX_MWEB".equals(channelId)) {
                    return "/pay/wxH5Sub.html";
                }
                return "/pay/sub.html";
            }else if(StringUtils.isNotBlank(payResult.getString("codeUrl"))) {//微信扫码支付
                String payUrl = payResult.getString("codeUrl");
                model.addAttribute("codeUrl",payUrl);
                if(payUrl.indexOf("http") == 0) {
                    response.sendRedirect(payUrl);
                }
                return "/pay/wxQrCodePayment.html";
            }else if(StringUtils.isNotBlank(payResult.getString("payParams"))) {//APP支付
                String payUrl = payResult.getString("payParams");
                model.addAttribute("payParams",payUrl);
                return "/pay/wxAppPayment.html";
            }else {
                return "/pay/confirmPayment.html";
            }
        }else{
            return "/pay/payError.html";
        }
    }
    /**
     * 下单完成支付
     * @param channelId
     * @return
     */
    @Deprecated
    @RequestMapping("/pay")
    public String pay(@RequestParam("channelId") String channelId,String payPassword,Model model, HttpSession session, HttpServletResponse response) throws IOException {
        String userId= (String) session.getAttribute("userId");
        ResponseModel checker=payService.checkUser(userId,payPassword);
        if(checker.getStatus().equals("0000")){
            model.addAttribute("msg",checker.getData());
            return "/pay/payMsg.html";
        }
        PayVo payVo= (PayVo) session.getAttribute("payVo");
        PayDto newPay= new PayDto();
        BeanUtils.copyProperties(payVo,newPay);
        channelId=newPay.getChannelId();
        System.out.println(newPay);
        String  s= (String) payService.pay(newPay);
        JSONObject jsonObject=JSONObject.parseObject(s);
        if(jsonObject.get("retCode").equals("FAIL")){
            return "/pay/payError.html";
        }
        //返回整个页面
        if(PayTool.checkChannel(channelId).equals(Constant.channelType1)){
            PrintWriter out = response.getWriter();
            out.write(jsonObject.get("payUrl").toString());
            out.close();
        }else if(PayTool.checkChannel(channelId).equals(Constant.channelType2)){
            System.out.println(jsonObject.get("payUrl").toString());
            PrintWriter out = response.getWriter();
            out.write(jsonObject.get("payUrl").toString());
            out.close();
        }else if(PayTool.checkChannel(channelId).equals(Constant.channelType3)){
            System.out.println("内部航旅支付"+newPay.getRedirectUrl());
            model.addAttribute("redirectUrl",newPay.getRedirectUrl());
            return "/pay/redirect.html";
        }
        return "/pay/payResult.html";
    }
    @PostMapping("payDirect")
    public ResponseModel payDirect(PayDto payDto){
        payDto.setNotifyUrl("");
        ResponseModel responseModel=new ResponseModel();
        String  s= (String) payService.pay(payDto);
        JSONObject jsonObject=JSONObject.parseObject(s);
        System.out.println(jsonObject.toJSONString());
        if(jsonObject.get("retCode").equals("FAIL")){
            responseModel.setStatus("0001");
            responseModel.setData(jsonObject.get("retMsg"));
        }else{
            responseModel.setStatus("0000");
            responseModel.setData(jsonObject.get("支付成功"));
        }
        return responseModel;
    }
    @RequestMapping("payError")
    public String payError(String msg,Model model){
        model.addAttribute("msg",msg);
        return "/pay/payError.html";
    }
}
